{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "52dc9b17-1182-44b3-bebf-ae2f508675d3",
   "metadata": {},
   "source": [
    "# Understanding Runtime Context and Session Management in AgentCore Runtime\n",
    "\n",
    "## Overview\n",
    "\n",
    "In this tutorial, we will learn how to understand and work with runtime context and session management in Amazon Bedrock AgentCore Runtime. This example demonstrates how AgentCore Runtime handles sessions, maintains context across multiple invocations, and how agents can access runtime information through the context object.\n",
    "\n",
    "Amazon Bedrock AgentCore Runtime provides isolated sessions for each user interaction, enabling agents to maintain context and state across multiple invocations while ensuring complete security isolation between different users.\n",
    "\n",
    "### Tutorial Details\n",
    "\n",
    "|Information| Details|\n",
    "|:--------------------|:---------------------------------------------------------------------------------|\n",
    "| Tutorial type       | Context and Session Management|\n",
    "| Agent type          | Single         |\n",
    "| Agentic Framework   | Strands Agents |\n",
    "| LLM model           | Anthropic Claude Sonnet 4 |\n",
    "| Tutorial components | Runtime Context, Session Management, AgentCore Runtime, Strands Agent and Amazon Bedrock Model |\n",
    "| Tutorial vertical   | Cross-vertical                                                                   |\n",
    "| Example complexity  | Intermediate                                                                     |\n",
    "| SDK used            | Amazon BedrockAgentCore Python SDK and boto3|\n",
    "\n",
    "### Tutorial Architecture\n",
    "\n",
    "In this tutorial, we will explore how Amazon Bedrock AgentCore Runtime manages sessions and provides context to agents. We'll demonstrate:\n",
    "\n",
    "1. **Session Continuity**: How the same session ID maintains context across multiple invocations\n",
    "2. **Context Object**: How agents can access runtime information through the context parameter\n",
    "3. **Session Isolation**: How different session IDs create completely isolated environments\n",
    "4. **Payload Flexibility**: How to pass custom data to agents through the payload\n",
    "\n",
    "For demonstration purposes, we will use a Strands Agent that showcases these session management capabilities.\n",
    "\n",
    "    \n",
    "<div style=\"text-align:left\">\n",
    "    <img src=\"images/architecture_runtime.png\" width=\"60%\"/>\n",
    "</div>\n",
    "\n",
    "### Tutorial Key Features\n",
    "\n",
    "* **Session-based Context Management**: Understanding how AgentCore Runtime maintains context within sessions\n",
    "* **Runtime Session Lifecycle**: Learning about session creation, maintenance, and termination\n",
    "* **Context Object Access**: Accessing runtime information like session ID through the context parameter\n",
    "* **Session Isolation**: Demonstrating how different sessions provide complete isolation\n",
    "* **Payload Handling**: Flexible data passing through custom payload structures\n",
    "* **Cross-invocation State**: Maintaining agent state across multiple calls within the same session"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3a676f58ecf52b42",
   "metadata": {},
   "source": [
    "## Prerequisites\n",
    "\n",
    "To execute this tutorial you will need:\n",
    "* Python 3.10+\n",
    "* AWS credentials\n",
    "* Amazon Bedrock AgentCore SDK\n",
    "* Strands Agents\n",
    "* Docker running\n",
    "\n",
    "## Understanding Amazon Bedrock AgentCore Runtime Sessions\n",
    "\n",
    "Before diving into the code, it's important to understand how Amazon Bedrock AgentCore Runtime manages sessions:\n",
    "\n",
    "### Session Isolation and Security\n",
    "\n",
    "AgentCore Runtime provides **complete session isolation** through dedicated microVMs:\n",
    "\n",
    "- **Dedicated Resources**: Each session runs in its own microVM with isolated CPU, memory, and filesystem\n",
    "- **Security Boundaries**: Complete separation between user sessions prevents data contamination\n",
    "- **Deterministic Cleanup**: After session completion, the microVM is terminated and memory is sanitized\n",
    "\n",
    "### Session Lifecycle\n",
    "\n",
    "Sessions in AgentCore Runtime follow a specific lifecycle:\n",
    "\n",
    "1. **Creation**: A new session is created on first invocation with a unique `runtimeSessionId`\n",
    "2. **Active State**: Session processes requests and maintains context\n",
    "3. **Idle State**: Session waits for next invocation while preserving context\n",
    "4. **Termination**: Session ends due to:\n",
    "   - Inactivity (15 minutes)\n",
    "   - Maximum lifetime (8 hours)\n",
    "   - Health check failures\n",
    "\n",
    "### Context Persistence\n",
    "\n",
    "Within a session, AgentCore Runtime maintains:\n",
    "- **Conversation History**: Previous interactions and responses\n",
    "- **Application State**: Variables and objects created during execution\n",
    "- **File System**: Any files created or modified during the session\n",
    "- **Environment Variables**: Custom settings and configurations\n",
    "\n",
    "### Session Management Best Practices\n",
    "\n",
    "- **Unique Session IDs**: Generate unique session IDs for each user or conversation\n",
    "- **Context Reuse**: Use the same session ID for related invocations to maintain context\n",
    "- **Session Boundaries**: Use different session IDs for different users or unrelated conversations\n",
    "- **Ephemeral Nature**: Don't rely on sessions for permanent data storage (use AgentCore Memory for persistence)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "initial_id",
   "metadata": {
    "jupyter": {
     "is_executing": true
    }
   },
   "outputs": [],
   "source": [
    "#!uv add -r requirements.txt --active"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "932110e6-fca6-47b6-b7c5-c4714a866a80",
   "metadata": {},
   "source": [
    "## Preparing your agent for deployment on AgentCore Runtime\n",
    "\n",
    "Let's now deploy our agent to AgentCore Runtime to demonstrate session management and context handling. Our agent will showcase how to:\n",
    "\n",
    "1. **Access Runtime Context**: Use the `context` parameter to get session information\n",
    "2. **Handle Custom Payloads**: Process structured data passed through the payload\n",
    "3. **Maintain Session State**: Keep track of user interactions within a session\n",
    "4. **Demonstrate Session Boundaries**: Show how different sessions are isolated\n",
    "\n",
    "### Understanding the Context Object\n",
    "\n",
    "The `context` object in AgentCore Runtime provides valuable information about the current execution environment:\n",
    "\n",
    "- **session_id**: The current runtime session identifier\n",
    "- **Runtime Metadata**: Information about the runtime environment\n",
    "- **Execution Details**: Context about the current invocation\n",
    "\n",
    "### Strands Agent with Context Handling\n",
    "\n",
    "Let's look at our implementation that demonstrates session management and context handling:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3b845b32-a03e-45c2-a2f0-2afba8069f47",
   "metadata": {},
   "outputs": [],
   "source": [
    "%%writefile strands_claude_context.py\n",
    "from strands import Agent, tool\n",
    "from strands_tools import calculator # Import the calculator tool\n",
    "import argparse\n",
    "import json\n",
    "from bedrock_agentcore.runtime import BedrockAgentCoreApp\n",
    "from strands.models import BedrockModel\n",
    "import asyncio\n",
    "from datetime import datetime\n",
    "\n",
    "app = BedrockAgentCoreApp()\n",
    "\n",
    "# Create a custom tool \n",
    "@tool\n",
    "def weather():\n",
    "    \"\"\" Get weather \"\"\" # Dummy implementation\n",
    "    return \"sunny\"\n",
    "\n",
    "@tool\n",
    "def get_time():\n",
    "    \"\"\" Get current time \"\"\"\n",
    "    return datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\")\n",
    "\n",
    "model_id = \"us.anthropic.claude-sonnet-4-20250514-v1:0\"\n",
    "model = BedrockModel(\n",
    "    model_id=model_id,\n",
    ")\n",
    "agent = Agent(\n",
    "    model=model,\n",
    "    tools=[\n",
    "        calculator, weather, get_time\n",
    "    ],\n",
    "    system_prompt=\"\"\"\n",
    "    You're a helpful assistant. You can do simple math calculations, \n",
    "    tell the weather, and provide the current time.\n",
    "    Always start by acknowledging the user's name \n",
    "    \"\"\"\n",
    ")\n",
    "\n",
    "def get_user_name(user_id):\n",
    "    users = {\n",
    "        \"1\": \"Maira\",\n",
    "        \"2\": \"Mani\",\n",
    "        \"3\": \"Mark\",\n",
    "        \"4\": \"Ishan\",\n",
    "        \"5\": \"Dhawal\"\n",
    "    }\n",
    "    return users[user_id]\n",
    "    \n",
    "@app.entrypoint\n",
    "def strands_agent_bedrock_handling_context(payload, context):\n",
    "    \"\"\"\n",
    "    AgentCore Runtime entrypoint that demonstrates context handling and session management.\n",
    "    \n",
    "    Args:\n",
    "        payload: The input payload containing user data and request information\n",
    "        context: The runtime context object containing session and execution information\n",
    "    \n",
    "    Returns:\n",
    "        str: The agent's response incorporating context information\n",
    "    \"\"\"\n",
    "    user_input = payload.get(\"prompt\")\n",
    "    user_id = payload.get(\"user_id\")\n",
    "    user_name = get_user_name(user_id)\n",
    "    \n",
    "    # Access runtime context information\n",
    "    print(\"=== Runtime Context Information ===\")\n",
    "    print(\"User id:\", user_id)\n",
    "    print(\"User Name:\", user_name)\n",
    "    print(\"User input:\", user_input)\n",
    "    print(\"Runtime Session ID:\", context.session_id)\n",
    "    print(\"Context Object Type:\", type(context))\n",
    "    print(\"=== End Context Information ===\")\n",
    "    \n",
    "    # Create a personalized prompt that includes context information\n",
    "    prompt = f\"\"\"My name is {user_name}. Here is my request: {user_input}\n",
    "    \n",
    "    Additional context: This is session {context.session_id}. \n",
    "    Please acknowledge my name and provide assistance.\"\"\"\n",
    "    \n",
    "    response = agent(prompt)\n",
    "    return response.message['content'][0]['text']\n",
    "\n",
    "if __name__ == \"__main__\":\n",
    "    app.run()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c64db7b5-0f1b-475f-9bf2-467b4449d46a",
   "metadata": {},
   "source": [
    "## Understanding Session Management in AgentCore Runtime\n",
    "\n",
    "The code above demonstrates several key concepts about how AgentCore Runtime manages sessions and provides context to agents:\n",
    "\n",
    "### Context Object Structure\n",
    "\n",
    "The `context` parameter in your entrypoint function provides access to runtime information:\n",
    "\n",
    "```python\n",
    "@app.entrypoint\n",
    "def strands_agent_bedrock_handling_context(payload, context):\n",
    "    # Access session information\n",
    "    session_id = context.session_id\n",
    "    # Use context information in your agent logic\n",
    "```\n",
    "\n",
    "### Session Continuity Benefits\n",
    "\n",
    "Within a single session, AgentCore Runtime provides:\n",
    "\n",
    "1. **Persistent Environment**: Variables and state persist across invocations\n",
    "2. **Context Preservation**: The agent can reference previous interactions\n",
    "3. **Resource Reuse**: Initialized models and tools remain loaded\n",
    "4. **Performance Benefits**: Reduced cold start times for subsequent invocations\n",
    "\n",
    "### Session Isolation Guarantees\n",
    "\n",
    "AgentCore Runtime ensures complete isolation between sessions:\n",
    "\n",
    "- **Security**: Each session runs in its own microVM with isolated resources\n",
    "- **Privacy**: No data leakage between different user sessions\n",
    "- **Reliability**: Issues in one session don't affect others\n",
    "- **Cleanup**: Complete memory sanitization after session termination\n",
    "\n",
    "### Payload Flexibility\n",
    "\n",
    "The `payload` parameter allows flexible data passing:\n",
    "\n",
    "```python\n",
    "# Example payload structures\n",
    "payload = {\n",
    "    \"prompt\": \"User's question\",\n",
    "    \"user_id\": \"1\",\n",
    "    \"preferences\": {...},\n",
    "    \"context_data\": {...}\n",
    "}\n",
    "```\n",
    "\n",
    "This enables rich, structured communication between clients and agents while maintaining the session context provided by the runtime."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d0861401-a111-4ade-9e02-50f52fdfa9b1",
   "metadata": {},
   "source": [
    "### Creating runtime role\n",
    "\n",
    "Before starting, let's create an IAM role for our AgentCore Runtime. We will do so using the utils function pre-developed for you."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "54dd2fdf-985c-4a70-8b87-071783a209de",
   "metadata": {},
   "outputs": [],
   "source": [
    "import sys\n",
    "import os\n",
    "\n",
    "# Get the current notebook's directory\n",
    "current_dir = os.path.dirname(os.path.abspath('__file__' if '__file__' in globals() else '.'))\n",
    "\n",
    "# Navigate up to the utils.py location\n",
    "utils_dir = os.path.join(current_dir, '..')\n",
    "utils_dir = os.path.join(utils_dir, '..')\n",
    "utils_dir = os.path.abspath(utils_dir)\n",
    "\n",
    "# Add to sys.path\n",
    "sys.path.insert(0, utils_dir)\n",
    "\n",
    "from utils import create_agentcore_role\n",
    "\n",
    "agent_name=\"strands_claude_context\"\n",
    "agentcore_iam_role = create_agentcore_role(agent_name=agent_name)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8855aceb-b79f-4aaa-b16f-8577c059816a",
   "metadata": {},
   "source": [
    "### Configure AgentCore Runtime deployment\n",
    "\n",
    "Next we will use our starter toolkit to configure the AgentCore Runtime deployment with an entrypoint, the execution role we just created and a requirements file. We will also configure the starter kit to auto create the Amazon ECR repository on launch.\n",
    "\n",
    "During the configure step, your docker file will be generated based on your application code\n",
    "\n",
    "<div style=\"text-align:left\">\n",
    "    <img src=\"images/configure.png\" width=\"60%\"/>\n",
    "</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2e79eba2-ca59-463f-9ebf-56e362d7ae66",
   "metadata": {},
   "outputs": [],
   "source": [
    "from bedrock_agentcore_starter_toolkit import Runtime\n",
    "from boto3.session import Session\n",
    "boto_session = Session()\n",
    "region = boto_session.region_name\n",
    "region\n",
    "\n",
    "agentcore_runtime = Runtime()\n",
    "\n",
    "response = agentcore_runtime.configure(\n",
    "    entrypoint=\"strands_claude_context.py\",\n",
    "    execution_role=agentcore_iam_role['Role']['Arn'],\n",
    "    auto_create_ecr=True,\n",
    "    requirements_file=\"requirements.txt\",\n",
    "    region=region,\n",
    "    agent_name=agent_name\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9e1b84cc-798e-472c-ac0b-2c315f4b704d",
   "metadata": {},
   "source": [
    "### Launching the context-aware agent to AgentCore Runtime\n",
    "\n",
    "Now that we've got a docker file, let's launch our context-aware agent to the AgentCore Runtime. This will create the Amazon ECR repository and the AgentCore Runtime.\n",
    "\n",
    "Our agent will demonstrate how AgentCore Runtime manages sessions and provides context information to agents.\n",
    "\n",
    "<div style=\"text-align:left\">\n",
    "    <img src=\"images/launch.png\" width=\"85%\"/>\n",
    "</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "17a32ab8-7701-4900-8055-e24364bdf35c",
   "metadata": {},
   "outputs": [],
   "source": [
    "launch_result = agentcore_runtime.launch()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a0ae9c09-09db-4a76-871a-92eacd96b9c3",
   "metadata": {},
   "source": [
    "### Checking for the AgentCore Runtime Status\n",
    "Now that we've deployed the AgentCore Runtime, let's check for it's deployment status"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "afa6ac09-9adb-4846-9fc1-4d12aeb74853",
   "metadata": {},
   "outputs": [],
   "source": [
    "import time\n",
    "\n",
    "status_response = agentcore_runtime.status()\n",
    "status = status_response.endpoint['status']\n",
    "end_status = ['READY', 'CREATE_FAILED', 'DELETE_FAILED', 'UPDATE_FAILED']\n",
    "while status not in end_status:\n",
    "    time.sleep(10)\n",
    "    status_response = agentcore_runtime.status()\n",
    "    status = status_response.endpoint['status']\n",
    "    print(status)\n",
    "status"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b7f89c56-918a-4cab-beaa-c7ac43a2ba29",
   "metadata": {},
   "source": [
    "## Demonstrating Session Management and Context Handling\n",
    "\n",
    "Now let's demonstrate the key session management features of AgentCore Runtime by testing different scenarios:\n",
    "\n",
    "### Scenario 1: Session Continuity\n",
    "We'll use the same session ID for multiple invocations to show how context is maintained.\n",
    "\n",
    "### Scenario 2: Session Isolation\n",
    "We'll use different session IDs to demonstrate complete isolation between sessions.\n",
    "\n",
    "### Scenario 3: Context Information Access\n",
    "We'll show how agents can access runtime context information.\n",
    "\n",
    "<div style=\"text-align:left\">\n",
    "    <img src=\"images/invoke.png\" width=\"85%\"/>\n",
    "</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3d909e42-e1a0-407f-84c2-3d16cc889cd3",
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "import uuid\n",
    "import json\n",
    "from IPython.display import Markdown, display\n",
    "\n",
    "# Create a session ID for demonstrating session continuity\n",
    "session_id = uuid.uuid4()\n",
    "print(f\"📋 Starting Session 1: {session_id}\")\n",
    "print(f\"👤 User: Maira (ID: 1)\")\n",
    "print(f\"❓ First question about weather\\n\")\n",
    "\n",
    "invoke_response = agentcore_runtime.invoke({\n",
    "    \"prompt\": \"How is the weather outside?\",\n",
    "    \"user_id\": \"1\"\n",
    "}, session_id=str(session_id))\n",
    "\n",
    "response_data = json.loads(invoke_response['response'][0])\n",
    "display(Markdown(response_data))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "086d49e5-426e-454e-89b3-eefacbe6a252",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Continue with the same session ID to demonstrate session continuity\n",
    "print(f\"🔄 Continuing Session 1: {session_id}\")\n",
    "print(f\"👤 Same user: Maira (ID: 1)\")\n",
    "print(f\"❓ Follow-up question about math\\n\")\n",
    "\n",
    "invoke_response = agentcore_runtime.invoke({\n",
    "    \"prompt\": \"How much is 2X5?\",\n",
    "    \"user_id\": \"1\"\n",
    "}, session_id=str(session_id))\n",
    "\n",
    "response_data = json.loads(invoke_response['response'][0])\n",
    "display(Markdown(response_data))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2a7899b9-68cd-487a-97be-80c7fb786bb1",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Continue with the same session ID - notice how the agent remembers the previous calculation\n",
    "print(f\"🔄 Continuing Session 1: {session_id}\")\n",
    "print(f\"👤 Same user: Maira (ID: 1)\")\n",
    "print(f\"❓ Building on previous answer - demonstrates context continuity\\n\")\n",
    "\n",
    "invoke_response = agentcore_runtime.invoke({\n",
    "    \"prompt\": \"and that plus 34?\",\n",
    "    \"user_id\": \"1\"\n",
    "}, session_id=str(session_id))\n",
    "\n",
    "response_data = json.loads(invoke_response['response'][0])\n",
    "display(Markdown(response_data))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7d4891d6-09b1-4111-b623-e3aa9d97a5c4",
   "metadata": {},
   "outputs": [],
   "source": [
    "# NEW SESSION - Demonstrate session isolation\n",
    "# Create a completely new session ID to show that context is lost\n",
    "new_session_id = uuid.uuid4()\n",
    "print(f\"🆕 Starting NEW Session 2: {new_session_id}\")\n",
    "print(f\"👤 Same user: Maira (ID: 1)\")\n",
    "print(f\"❓ Attempting to reference previous calculation - should fail due to session isolation\\n\")\n",
    "\n",
    "invoke_response = agentcore_runtime.invoke({\n",
    "    \"prompt\": \"And plus 10?\",\n",
    "    \"user_id\": \"1\"\n",
    "}, session_id=str(new_session_id))\n",
    "\n",
    "response_data = json.loads(invoke_response['response'][0])\n",
    "display(Markdown(response_data))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "89d50551-bbee-45a9-8c33-29350e3ed9b6",
   "metadata": {},
   "outputs": [],
   "source": [
    "# NEW SESSION AND USER - Demonstrate complete isolation\n",
    "different_user_session = uuid.uuid4()\n",
    "print(f\"🆕 Starting Session 3: {different_user_session}\")\n",
    "print(f\"👤 Different user: Mani (ID: 2)\")\n",
    "print(f\"❓ Same question as first user - demonstrates user isolation\\n\")\n",
    "\n",
    "invoke_response = agentcore_runtime.invoke({\n",
    "    \"prompt\": \"How is the weather?\",\n",
    "    \"user_id\": \"2\"\n",
    "}, session_id=str(different_user_session))\n",
    "\n",
    "response_data = json.loads(invoke_response['response'][0])\n",
    "display(Markdown(response_data))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7d3fdfe404469632",
   "metadata": {},
   "source": [
    "## Understanding the Session Management Results\n",
    "\n",
    "The demonstrations above showcase several key aspects of AgentCore Runtime's session management:\n",
    "\n",
    "### 1. Session Continuity (Session 1)\n",
    "- **First invocation**: Agent responds to weather question and acknowledges user name\n",
    "- **Second invocation**: Agent performs calculation (2×5=10)\n",
    "- **Third invocation**: Agent references previous result (\"that plus 34\" = 44)\n",
    "\n",
    "**Key Learning**: The agent maintained context across multiple invocations within the same session, remembering the calculation result from the previous interaction.\n",
    "\n",
    "### 2. Session Isolation (Session 2)\n",
    "- **New session ID**: Created a completely new session\n",
    "- **Same user**: Used the same user ID but different session\n",
    "- **Context loss**: Agent cannot reference previous calculation\n",
    "\n",
    "**Key Learning**: Even with the same user, a new session creates a completely isolated environment with no access to previous context.\n",
    "\n",
    "### 3. User and Session Isolation (Session 3)\n",
    "- **Different user**: Mani instead of Maira\n",
    "- **New session**: Complete isolation from previous sessions\n",
    "- **Fresh context**: Agent starts with clean state\n",
    "\n",
    "**Key Learning**: Each session provides complete isolation, ensuring privacy and security between different users and interactions.\n",
    "\n",
    "### 4. Context Object Usage\n",
    "Throughout all invocations, the agent:\n",
    "- Accessed the runtime context via `context.session_id`\n",
    "- Processed custom payload data (`user_id`, `prompt`)\n",
    "- Maintained logging and debugging information\n",
    "\n",
    "**Key Learning**: The context object provides valuable runtime information that agents can use for enhanced functionality and debugging.\n",
    "\n",
    "### Session Management Best Practices Demonstrated\n",
    "\n",
    "1. **Use consistent session IDs** for conversational continuity\n",
    "2. **Generate unique session IDs** for different users or conversations\n",
    "3. **Leverage context information** for enhanced agent behavior\n",
    "4. **Design for session boundaries** - don't assume persistence across sessions\n",
    "5. **Handle graceful context loss** when sessions change or expire\n",
    "\n",
    "## Cleanup (Optional)\n",
    "\n",
    "Let's now clean up the AgentCore Runtime created"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7c243e86-a214-483c-aef1-d5243f28ca9e",
   "metadata": {},
   "outputs": [],
   "source": [
    "launch_result.ecr_uri, launch_result.agent_id, launch_result.ecr_uri.split('/')[1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "76a6cf1416830a54",
   "metadata": {},
   "outputs": [],
   "source": [
    "import boto3\n",
    "\n",
    "agentcore_control_client = boto3.client(\n",
    "    'bedrock-agentcore-control',\n",
    "    region_name=region\n",
    ")\n",
    "ecr_client = boto3.client(\n",
    "    'ecr',\n",
    "    region_name=region\n",
    "    \n",
    ")\n",
    "\n",
    "iam_client = boto3.client('iam')\n",
    "\n",
    "runtime_delete_response = agentcore_control_client.delete_agent_runtime(\n",
    "    agentRuntimeId=launch_result.agent_id,\n",
    "    \n",
    ")\n",
    "\n",
    "response = ecr_client.delete_repository(\n",
    "    repositoryName=launch_result.ecr_uri.split('/')[1],\n",
    "    force=True\n",
    ")\n",
    "\n",
    "policies = iam_client.list_role_policies(\n",
    "    RoleName=agentcore_iam_role['Role']['RoleName'],\n",
    "    MaxItems=100\n",
    ")\n",
    "\n",
    "for policy_name in policies['PolicyNames']:\n",
    "    iam_client.delete_role_policy(\n",
    "        RoleName=agentcore_iam_role['Role']['RoleName'],\n",
    "        PolicyName=policy_name\n",
    "    )\n",
    "iam_response = iam_client.delete_role(\n",
    "    RoleName=agentcore_iam_role['Role']['RoleName']\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b118ad38-feeb-4d1d-9d57-e5c845becc56",
   "metadata": {},
   "source": [
    "# Congratulations!\n",
    "\n",
    "You have successfully implemented and tested session management and context handling with Amazon Bedrock AgentCore Runtime! \n",
    "\n",
    "## What you've learned:\n",
    "\n",
    "### Session Management Fundamentals\n",
    "* **Session Continuity**: How the same session ID maintains context across multiple invocations\n",
    "* **Session Isolation**: How different session IDs create completely isolated environments\n",
    "* **Context Preservation**: How agents can maintain state and reference previous interactions\n",
    "* **Security Boundaries**: How AgentCore Runtime ensures complete isolation between users\n",
    "\n",
    "### Runtime Context Handling\n",
    "* **Context Object Access**: How to access runtime information via the `context` parameter\n",
    "* **Session Information**: How to retrieve and use session IDs in your agent logic\n",
    "* **Payload Processing**: How to handle structured data passed through custom payloads\n",
    "* **Runtime Metadata**: How agents can access execution environment information\n",
    "\n",
    "### AgentCore Runtime Architecture\n",
    "* **MicroVM Isolation**: Each session runs in its own isolated microVM\n",
    "* **Resource Management**: Dedicated CPU, memory, and filesystem per session\n",
    "* **Security Model**: Complete memory sanitization after session termination\n",
    "* **Lifecycle Management**: Session states (active, idle, terminated) and timeouts\n",
    "\n",
    "### Best Practices Implementation\n",
    "* **Session ID Generation**: Creating unique identifiers for different conversations\n",
    "* **Context Utilization**: Leveraging runtime context for enhanced agent behavior\n",
    "* **State Management**: Understanding ephemeral vs persistent state\n",
    "* **Error Handling**: Graceful handling of context loss and session boundaries"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.18"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
